CognitoをプライベートなSAML IdPと連携してみた

CognitoをプライベートなSAML IdPと連携してみた

CognitoはSAMLを使った外部IdP連携に対応しています。 Cognitoの場合、メタデータをファイルアップロードで設定できるので、理論上はCognitoと外部IdP間の通信ができなくても、SAML IdPとして連携できます。 この構成で本当に連携できるのか実際に試してみました。
Clock Icon2024.11.19

CognitoはSAMLを使った外部IdP(Identity Provider)連携に対応しています。

弊社ブログでも、CognitoとSAMLの外部IdP連携について解説しているものがあります。

SAMLは、SAML AssertionをSAML IdPとSP(Service Provider)間でやり取りし、IdP側でユーザー認証した結果をレスポンスします。

その際、SAML Assertionを検証するために、SP側(Cognito)にはIdPのメタデータ(公開鍵)が必要です。

Cognitoの場合、IdPのメタデータはURL形式で指定して自動取得するか、ファイルアップロードで設定できます。

メタデータの取得がファイルアップロードでできるので、理論上はCognitoと外部IdP間の通信ができなくても、SAML IdPとして連携できます。

この構成で本当に連携できるのか、実際に試してみました。

AWS構成図

こんな環境作っていきます。

image.png

Cognitoのログイン環境として、ALB+Cognitoを利用します。

ALB+Cognitoを組み合わせた認証については、弊社ブログで解説しているのでこちらをご覧ください。
この先、ALB+Cognito環境は構築済みであるという前提で進めます。

そこに、外部IdPとしてローカル環境に構築した、SAML IdPを追加します。

ローカル環境につくることで、CognitoからSAML IdPへ通信できない状況を再現します。

検証用SAML IdP環境の構築

こちらのブログを参考にさせてもらい、 saml-idp コマンドを利用してSAML IdP環境を構築します。

openssl コマンドでIdP用の証明書ファイルを作成します。
Country Name(国名)等は検証用途なので適当に入力します。

$ openssl req -x509 -new -noenc \
  -newkey rsa:2048 \
  -keyout idp-private-key.pem \
  -out idp-public-cert.pem \
  -days 7300

証明書が作成できたら、 saml-idp コマンドを使ってIdP環境を起動します。

$ export ENTITY_ID="<<CognitoのSP Entity ID>>"
$ export ACS_URL="<<CognitoのACS URL>>"
$ saml-idp \
  --acs ${ACS_URL} \
  --aud ${ENTITY_ID}

CognitoのSP Entity IDは、次のような形式です。
ユーザープールIDによって異なります。

  • urn:amazon:cognito:sp:<<ユーザープールID>>

CognitoのACS URLは、次のような形式です。

起動できたら、ブラウザで http://localhost:7000 にアクセスします。

SAML IdPのメタデータはこちらからダウンロードできます。

image.png

これでSAML IdP環境側は準備完了です。

CognitoのSAML IdP連携設定

Cognitoの「サインインエクスペリエンス」タブから、SAML IdPの設定をします。

cognito1.png

「アイデンティティプロバイダー」にSAMLを選択して、プロバイダー名を適当に入力します。
今回は saml-test という名前にしました。

cognito2.png

メタデータドキュメントのソースで「メタデータドキュメントをアップロード」を選択し、先ほどダウンロードしたメタデータファイルをアップロードします。

cognito3.png

「SAMLプロバイダーとユーザープールの間で属性をマッピング」では、SAML IdPから返される属性をユーザープールの属性にマッピングします。
どういう属性が連携されるかは、SAML IdP側の仕様を確認してください。

cognito4.png

saml-idp の場合は、メタデータに記載されている属性が連携されます。
今回は、ユーザープールの email 属性に email 属性を、 ユーザープールの given_name 属性に displayName 属性をマッピングして連携するようにしてみます。

metadata.png

次にCognitoのアプリケーションの統合タブから、SAML IdP用のアプリケーションクライアントを作成します。

cognito5.png

ALBでCognitoを使用するために必要な設定は割愛します。先ほど紹介したブログを参考にしてください。

このブログでは、SAML IdP連携で必要な設定のみ紹介します。

IDプロバイダーに先ほど設定したSAML IdP用のプロバイダー名を選択します。Cognitoユーザープールは選択から外します。

cognito6.png

これでCognitoとSAML IdPの連携設定は完了です。

動作確認

実際にログインしてみます。

開発者ツールで記録を取りながら、ALBのドメインにアクセスすると、CognitoのHosted UIにリダイレクトされて、SAML IdPのログイン画面にリダイレクトされる動きが見えます。

image.png

想定通り動けばここに表示されている、Display NameとE-Mail AddressがCognitoに連携されるんだなーという気持ちで、Sign inボタンを押します。

image.png

そうすると、CognitoにSAMLレスポンスが渡って、ALB側にリダイレクトされてCognitoから認可コードを受け取り、ログインが完了して最終的にEC2のコンテンツが表示されます。

image.png

ログイン後に、Cognitoユーザープールのユーザーも見てみると、emailとDisplayNameがCognito側にも連携されていることが確認できます。

image.png

うまくいかない場合は、SAML IdP側の設定にも注意が必要です。
この辺がうまく設定できていないと連携に失敗します。

image.png
image.png

重要な注意点

SAMLメタデータには公開鍵が含まれており、公開鍵には有効期限があります。

通常であれば、有効期限前にSAML IdP側が秘密鍵と公開鍵を更新して、メタデータを更新することになります。

その場合、メタデータをアップロードしているCognito側もメタデータを手動で更新する必要があることに注意してください。

今回の構成の場合、SAML IdP側がプライベートネットワークにあるので不可能ですが、
SAML IdPにメタデータのパブリックエンドポイントがあればそちらを利用することを推奨しています。

パブリックエンドポイントがあれば、Cognitoが自動で更新してくれます。

おわりに

CognitoとSAML IdPの連携について、Cognito側からSAML IdP側へ通信ができなくても連携できることを確認しました。

ドキュメント読んだ限り、理論上はできそうだけど本当にできるのかなってところが確かめられて良かったです。

このブログがどなたかのお役に立てれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.